import threading

class CancellableTimer(threading.Thread):
    """Call a function after a specified number of seconds:

            t = Timer(30.0, f, args=None, kwargs=None)
            t.start()
            t.cancel()     # stop the timer's action if it's still waiting

    """

    def __init__(self, interval, function, args=None, kwargs=None):
        """ just do like threading.Timer does """
        threading.Thread.__init__(self)
        self.interval = interval
        self.function = function
        self.args = args if args is not None else []
        self.kwargs = kwargs if kwargs is not None else {}
        self.finished = threading.Event()

    def cancel(self):
        """ atomic cancel this timer, 
            if True, it means successfully cancelled,
            if False, it means it's already executing or stopped already
        """
        if self.finished.is_set():
            return False
        else:
            self.finished.set()
            return True

    def test_and_set(self):
        with self.finished._cond:
            if not self.finished._flag:
                self.finished._flag = False
                self.finished._cond.notify_all()
                return False
            else:
                return True

    def run(self):
        self.finished.wait(self.interval)
        if not self.test_and_set():
            """ if event is not set """
            self.function(*self.args, **self.kwargs)